package pt.isel.pdm.ouryamba;

import java.util.List;
import winterwell.jtwitter.Twitter.Status;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;

public class TimelineActivity extends BaseActivity implements OnItemClickListener, Runnable
{
		
	private ListView timelineListView;
	private DetailFragment detailFragment;
	private Intent refreshIntent;
	public static final String ID = TimelineActivity.class.getName();
	
	
//Own methods
	
	/**
	 * Extracts the status id from the view of one item from the ListView.
	 * 
	 * @param itemView Is the view of a single status in the ListView.
	 *  @see General#log(String)
	 *  @see General#logException(Exception)
	 * */
	private Long extractId(View itemView) 
	{
		try
		{
			String la = (String) ((TextView) itemView.findViewById(R.id.idMessageId)).getText();
			return Long.valueOf(la);
		}
		catch (Exception e)
		{
			app.log("TimelineActivity.extractId(): Exception thrown.");
			app.logException(e);
			return General.DEFAULT_STATUS_SELECTED_ID;
		}
	}
	
	/**
	 * Send the intent to the TimelinePullService to fetch new status from the server.</br>
	 * 
	 * Register this instance as a waiter for the service to notify.</br>
	 * 
	 * If the layout is in landscape, the views from the DetaiFragment are notified to state
	 * the "refresh" word.
	 * 
	 * @see DetailFragment#updateViewElements(boolean)
	 * @see General#setStatusSelectedId(Long)
	 * @see Waiter#Wait()
	 * */
	private void refreshTimeline()
	{
		if(detailFragment != null)
		{
			detailFragment.updateViewElements(true);
			app.setStatusSelectedId(General.DEFAULT_STATUS_SELECTED_ID);
		}
		if(refreshIntent == null)
		{
			refreshIntent = new Intent(this, TimelinePullService.class);
		}
		app.waiter.Wait(this, this);
		startService(refreshIntent);
	}
	
	/**
	 * Update the ListView with status from the database.</br>
	 * 
	 * If the database is empty, a Toast object is shown so user acknowledge that. It is
	 * also notified that the timeline was seen (to control the notifications state)</br>
	 * 
	 * If the layout is in landscape, the views from the DetaiFragment are notified to state
	 * the "refresh" word.
	 * 
	 * @see General#dbSelectByCommittedValue(boolean)
	 * @see General#showToast(int)
	 * @see General#timelineSeen(long)
	 * @see General#convertToPostList(List)
	 * @see DetailFragment#updateViewElements(boolean)
	 * */
	private void updateFromDb()
	{
		List<Status> list = app.dbSelectByCommittedValue(true);
		if(list.size() == 0)
		{
			app.showToast(R.string.databaseEmpty);
		}
		else
		{
			app.timelineSeen(list.get(0).id);
		}
		setAdapter(app.convertToPostList(list));
		if(detailFragment != null)
		{
			detailFragment.updateViewElements(false);
		}
	}
	
	/**
	 * Set the adapter of the ListView with objects received by parameter.
	 * 
	 * @param list Is the list of status to set in the adapter.
	 * */
	private void setAdapter(List<Post> list)
	{
		String[] adapterCollumns = {
			DbStatusContract.MESSAGE, 
			DbStatusContract.USER_NAME, 
			DbStatusContract.CREATED_AT, 
			DbStatusContract.ID};
		int[] adapterViews = {
			R.id.idMessageText, 
			R.id.idMessageAuthor, 
			R.id.idMessageTime,
			R.id.idMessageId};
		SimpleAdapter adapter = new SimpleAdapter(getApplicationContext(), list, R.layout.timeline_item, adapterCollumns, adapterViews);
		timelineListView.setAdapter(adapter);
	}
	
	
//Activity methods
	
	/**
	 * Perform some initializing procedures for this activity lifetime.</br>
	 * 
	 * Set a reference for this activity on the General class so other components can know when this activity 
	 * is being shown or not.</br>
	 * Append one listener to the listview and sign that to this instance so when the status is
	 * clicked, the code executed is from this class ({@code onItemClick()} method).
	 * If the preference option about automatic updates is enable, it is sent an intent to the TimelinePullService
	 * to start the updater thread which is responsible to perform automatic updates.</br>
	 * 
	 * Also is started the StatusUploadService because if exists network connectivity and status to be upload, this is 
	 * instant good to do that.
	 * 
	 * @see General#getAutomaticUpdate()
	 * @see #updateFromDb()
	 * @see General#startServices()
	 * */
	@Override
	public void onCreate(Bundle savedInstanceState) 
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_timeline);
		app.timelineActivity.set(this);
		timelineListView = (ListView)findViewById(R.id.timelineListView);
		timelineListView.setClickable(true);
		timelineListView.setOnItemClickListener(this);
		if(app.getAutomaticUpdate())
		{
			Intent updaterIntent = new Intent(this, TimelinePullService.class).putExtra(TimelinePullService.ARG_ACTION_TYPE, TimelinePullService.ARG_START_AUTOMATIC_UPDATE);
			startService(updaterIntent);
			updaterIntent = null;
		}
		updateFromDb();
		app.startServices();
	}
	
	/**
	 * Perform some visual enhancements.</br>
	 * 
	 * If layout is in landscape updates the views from the detail fragment.
	 * 
	 * @see General#getStatusSelectedId()
	 * @see DetailFragment#updateViewElements(boolean)
	 * */
	@Override
	public void onResume()
	{
		if(app.getStatusSelectedId() == General.DEFAULT_STATUS_SELECTED_ID)
		{
			timelineListView.setItemChecked(0, true);			
		}
		if(findViewById(R.id.detailFragment) != null)
		{
			detailFragment = (DetailFragment) getFragmentManager().findFragmentById(R.id.detailFragment);
		}
		if(detailFragment != null)
		{
			detailFragment.updateViewElements(false);			
		}
		super.onResume();
	}
	
	/**
	 * Delegates the behavior for each menu item when it's clicked.
	 * 
	 * When the item clicked is the refresh option, the action is to call the method refreshTimeline()
	 * of this class.
	 * 
	 * If the item clicked is not a responsibility of this activity, the decision is given to the
	 * BaseActivity with the {@code super} call on the default closure.
	 * 
	 * @see #refreshTimeline()
	 * @see BaseActivity#onOptionsItemSelected(MenuItem)
	 * */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) 
	{
		switch(item.getItemId())
		{
			case R.id.action_refresh:
				refreshTimeline();
				return true;
			default:
				return super.onOptionsItemSelected(item);
		}
	}	
	
	/**
   	 * Sets some menu items invisible (the ones that don't matter for this Activity).
   	 * 
   	 * Hide the timeline menu item because there is none sense having that here.
   	 * */
	@Override
	public boolean onCreateOptionsMenu(Menu menu) 
	{
		getMenuInflater().inflate(R.menu.shared_menu, menu);
		menu.getItem(1).setVisible(false);
		return true;
	}
	
	/**
	 * Set some variable to null to help GC, remove the reference of this instance from the General class.
	 * 
	 * @see General#setStatusSelectedId(Long)
	 * */
	@Override
	public void onDestroy()
	{
		if(refreshIntent != null)
		{
   			stopService(refreshIntent);
   			refreshIntent = null;
		}
		app.timelineActivity.set(null);
		app.setStatusSelectedId(General.DEFAULT_STATUS_SELECTED_ID);
		super.onDestroy();
	}
	
	
//OnItemClickListener methods
	
	/**
	 * Delegates the behavior when some item in the list is clicked. </br>
	 * 
	 * When some item is clicked, we store the id of the status that was clicked inside the General 
	 * class, so when the DetailActivity is created (or the detail fragment updated) the value
	 * can be fetched from there.</br>
	 *
	 * @see General#setStatusSelectedId(Long)
	 * @see #extractId(View)
	 * @see DetailFragment#updateViewElements(boolean)
	 * */
	@Override
	public void onItemClick(AdapterView<?> listView, View itemView, int position, long id) 
	{
		app.setStatusSelectedId(extractId(itemView));
		if(detailFragment == null)
		{
			startActivity(new Intent(getApplicationContext(), DetailActivity.class));			
		}
		else
		{
			detailFragment.updateViewElements(false);
		}
	}


//Runnable methods
	

	/**
	 * Update the ListView with status form the database.</br>
	 * 
	 * This callback is executed when the database was updated with new statuses.
	 * 
	 * @see General#showToast(int)
	 * @see #updateFromDb()
	 * */
	@Override
	public void run()
	{
		if(this.hasWindowFocus())
		{
			app.showToast(R.string.timelineUpdated);
		}
		updateFromDb();
	}

}
